from decimal import Decimal

from django.db import transaction
from django.utils import timezone
from rest_framework import serializers
from goods.models import SKU
from .models import OrderInfo, OrderGoods
from django_redis import get_redis_connection


# 結算展示序列化器
class OrderPlaceSerializer(serializers.ModelSerializer):
    count = serializers.IntegerField(min_value=1, label="商品數量")

    class Meta:
        model = SKU
        fields = ("id", "count", "name", "price", "default_image_url")


# 創建訂單
class OrderCommitSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderInfo
        fields = ("address", "pay_method", "order_id")

        read_only_fields = ["order_id"]  # 序列化的時候用(也就是返回的時候用,反序列化的時候不用)

        # write_only 是反序列化的時候用,序列化的時候不用
        extra_kwargs = {
            "address": {
                "write_only": True
            },
            "pay_method": {
                "write_only": True
            }
        }

    # 重寫create方法,去除redis數據,創建訂單對象,創建訂單商品對象
    # 事務開啓裝飾器
    @transaction.atomic
    def create(self, validated_data):

        # 獲取user
        user = self.context["request"].user

        # 創建訂單號(確保唯一)
        order_id = timezone.now().strftime("%Y%m%d%H%M%S") + "%06d" % user.id

        # 獲取地址
        address = validated_data["address"]

        # 獲取支付方式
        pay_method = validated_data["pay_method"]

        # 訂單狀態
        if pay_method == OrderInfo.PAY_METHODS_ENUM["CASH"]:
            status = OrderInfo.ORDER_STATUS_ENUM["UNPAID"]
        else:
            status = OrderInfo.ORDER_STATUS_ENUM["UNSEND"]

        # 設置保存點
        sid = transaction.savepoint()

        # 創建訂單信息對象
        order = OrderInfo.objects.create(
            order_id=order_id,
            user=user,
            address=address,
            total_count=0,
            total_amount=Decimal(0.0),
            freight=Decimal(10.0),
            pay_method=pay_method,
            status=status
        )

        # 獲取redis中的數據
        redis_conn = get_redis_connection("cart")
        cart_dict = redis_conn.hgetall("cart_%s" % user.id)
        cart_selected_list = redis_conn.smembers("cart_selected_%s" % user.id)

        # 遍歷創建訂單對象
        for sku_id in cart_selected_list:
            while True:

                # 獲取商品對象,數量
                sku = SKU.objects.get(id=sku_id)
                count = int(cart_dict[sku_id])

                # 判斷庫存量是否足夠
                if count > sku.stock:

                    # 回滾
                    transaction.savepoint_rollback(sid)

                    raise serializers.ValidationError("庫存不足")

                # 減少庫存,增加銷量
                # sku.stock -= count
                # sku.sales += count
                # sku.save()

                # 使用樂觀鎖,解決並發問題
                old_stock = sku.stock
                old_sales = sku.sales
                new_stock = old_stock - count
                new_sales = old_sales + count
                ret = SKU.objects.filter(id=sku_id,stock=old_stock).update(stock=new_stock,sales=new_sales)

                if ret == 0:
                    # 繼續查詢一次庫存
                    continue

                # 累加商品數量和價格
                order.total_count += count
                order.total_amount += (sku.price * count)

                # 創建訂單商品對象
                OrderGoods.objects.create(
                    order=order,
                    sku=sku,
                    count=count,
                    price=sku.price
                )
                # 必須退出循環
                break
        # 保存,清除redis中的數據
        order.save()

        # 提交
        transaction.savepoint_commit(sid)

        redis_conn.hdel("cart_%s" % user.id, *cart_selected_list)
        redis_conn.srem("cart_selected_%s" % user.id, *cart_selected_list)

        # 返回響應
        return order
